#ifndef __TINY_TEST__

#include "vbb_GSM_CNS01.h"
#include "fw/vbb_RTC.h"
#include "vbb_GSM_Communicator.h"
#include <stdio.h>

extern VBB_Pin PWRKEY_Pin;
extern VBB_Pin STATUS_Pin;

bool GSM_IsOn_CNS01(void)
{
    return (GSM_Command("AT\r", "OK", "ERROR", NULL, NULL, 2) == 1);
}

bool GSM_Ready_CNS01(void)
{
    return (GSM_Command("AT\r", "OK", "ERROR", NULL, NULL, 2) == 1);
}

void GSM_Reboot_CNS01(void)
{
    vbb_PIN_Set(&STATUS_Pin, TRUE);    
    vbb_PIN_Set(&PWRKEY_Pin, TRUE);    
    vbb_DelayMillis(50);
    vbb_PIN_Set(&PWRKEY_Pin, FALSE);
    vbb_DelayMillis(50);
    vbb_PIN_Set(&PWRKEY_Pin, TRUE);        
    vbb_PIN_Set(&STATUS_Pin, TRUE);
}

void GSM_SetUp_CNS01(void)
{     
    vbb_OUTPUT_Print("INFO: GSM module settings up...");
    
    GSM_Command("ATZ\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("AT&F\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("ATE0\r", "OK", "ERROR", NULL, NULL, 5);    
    
    GSM_Command("AT+CFUN=1\r", "OK", "ERROR", NULL, NULL, 5); // I'm not sure if it supports CNS03    
    GSM_Command("AT+CREG=0\r", "OK", "ERROR", NULL, NULL, 5); // Turn off annoying messages +CREG    
    
    vbb_OUTPUT_Print("[DONE]\r\n");
}

extern char _gsm_Server[64];
extern char _gsm_ServerDoc[256];

extern char _gsm_tmpCmd[256];
extern char _gsm_tmpCmd2[256];

extern char _gsm_tmp[1024];
extern VBB_USART gsmUsart;

extern VBB_Message gsmMessage;

bool GSM_GPRS_IsOpen_CNS01(void)
{
    return GSM_Command("AT+CGATT?\r", "+CGATT: 1", "+CGATT: 0", "ERROR", "OK", 5) == 1;
}

char GSM_GPRS_Open_CNS01(void)
{  
    if (GSM_Command("AT+CREG?\r", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", 5) == 1)
    {                
        if (!GSM_GPRS_IsOpen())
        {            
            GSM_Command("AT+CGAUTO=1\r", "OK", "ERROR", NULL, NULL, 10);
            return TRUE;
        }
        else
            return FALSE;
    }
    else
    {
        vbb_OUTPUT_Print("DEBUG: SIM card error.\r\n");
        return FALSE;
    }
}

char GSM_GPRS_WaitForOpen_CNS01(void)
{
    if (GSM_GPRS_IsOpen())
        return GPRS_ATTACHED;
    else
        return GPRS_ATTACHING;
}

char GSM_NetworkSet_CNS01(void)
{
    char ret = GSM_Command("AT+COPS?\r", "VIETTEL", "MOBIFONE", "VINAPHONE", "OK", 5);
    if (ret == 4)
        ret = GSM_Command("AT+COPS?\r", "Viettel", "Mobifone", "Vinaphone", "OK", 5);
    
    GSM_Command("AT^SICS=0,conType,GPRS0\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("AT^SICS=0,alphabet,0\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("AT^SICS=0,inactTO,60\r", "OK", "ERROR", NULL, NULL, 5);
    
    if (ret == 1)
    {
        vbb_OUTPUT_Print("DEBUG: Use GPRS settings for Viettel network.\r\n");
        GSM_Command("AT^SICS=0,apn,\"v-internet\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,user,\"\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,passwd,\"\"\r", "OK", "ERROR", NULL, NULL, 5);
    }
    else if (ret == 2 || ret == 3)
    {
        vbb_OUTPUT_Print("DEBUG: Use GPRS settings for VNPT network.\r\n");
        GSM_Command("AT^SICS=0,apn,\"m-wap\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,user,\"mms\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,passwd,\"mms\"\r", "OK", "ERROR", NULL, NULL, 5);
    }
    else
    {
        vbb_OUTPUT_Print("DEBUG: Use GPRS settings for unknown network.\r\n");
        GSM_Command("AT^SICS=0,apn,\"m-wap\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,user,\"mms\"\r", "OK", "ERROR", NULL, NULL, 5);
        GSM_Command("AT^SICS=0,passwd,\"mms\"\r", "OK", "ERROR", NULL, NULL, 5);
    }
    
    GSM_Command("AT^SISS=0,srvType,\"Socket\"\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("AT^SISS=0,conId,0\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_Command("AT^SISS=0,alphabet,1\r", "OK", "ERROR", NULL, NULL, 5);
    
    return ret;
}

bool GSM_TCP_IsOpen_CNS01(void)
{
    int ret = GSM_Command("AT^SISI=0\r", "^SISI: 0,4", "^SISI: 0,3", "OK", "ERROR", 5);
    if (ret == 1)    
        return TRUE;
    else
        return FALSE;
}

char GSM_TCP_Open_CNS01(const char * ServerAddr)
{
    sprintf(_gsm_tmpCmd, "AT^SISS=0,address,\"socktcp://%s\"\r", ServerAddr);
    GSM_Command(_gsm_tmpCmd, "OK", "ERROR", NULL, NULL, 5);
    
    if (GSM_Command("AT^SISI=0\r", "^SISI: 0,4", "^SISI: 0,3", "OK", "ERROR", 5) != 3)
    {
        vbb_OUTPUT_Print("INFO: Stuck in connection. Reboot to solve.\r\n");
        vbb_Reset();
    }
    
    GSM_Command("AT^SISC=0\r", "OK", "ERROR", NULL, NULL, 5);
    GSM_PutCommand("AT^SISO=0\r");
    return TRUE;
}

char GSM_TCP_WaitForOpen_CNS01(void)
{
    int ret = GSM_WaitForAnswerUpdate("^SISW: 0, 1\r\n", NULL, NULL, NULL, CONNECTION_TIMEOUT);
    if (GSM_CommandFinished())
    {
        if (ret == 1)
            return TCP_CONNECTION_UP;
        else
            return TCP_CONNECTION_DOWN;
    }
    return TCP_CONNECTION_CONNECTING;
}

char GSM_TCP_Opened_CNS01(const char * Document, char * DataBuffer, int * DataSize, char * TmpBuffer)
{
    GSM_BuildDataBuffer(Document, DataBuffer, DataSize, TmpBuffer);    
    return TRUE;
}

char * wait_command;
char * wait_value;

int wait_sendSize;

char GSM_TCP_DataWaitForReady_CNS01(void)
{
    int ret = GSM_WaitForAnswerUpdate(wait_value, "ERROR", NULL, NULL, 5);
    if (GSM_CommandFinished())
    {
        if (ret == 1)
            return TRUE;
        else
            return FALSE;
    }
    else        
        return FALSE;
}

int GSM_TCP_DataPrepareSend_CNS01(char * DataBuffer, int DataSize)
{    
    wait_command = _gsm_tmpCmd;
    wait_value = _gsm_tmpCmd2;    
    
    wait_sendSize = GET_MIN(DataSize, 1024);    
    if (wait_sendSize > 0)
    {
        sprintf(wait_command, "AT^SISW=0,%d,0,0\r", wait_sendSize);
        sprintf(wait_value, "^SISW: 0, %d,", wait_sendSize);
        
        GSM_PutCommand(wait_command);        
    }
    return wait_sendSize;
}

int GSM_TCP_DataSendData_CNS01(char * DataBuffer, int SendSize)
{
    int i;    
    for (i = 0; i < SendSize; i++)
    {
        GSM_WriteByte(DataBuffer[i]);    
        //vbb_OUTPUT_WriteByte(DataBuffer[i]);
    }
    
    i = GSM_Command("", "\r\nOK\r\n", "\r\nERROR\r\n", NULL, NULL, 10);
    if (i == 1)
        return SendSize;
    else
        return -1;
}

char GSM_TCP_WaitForServerClosed_CNS01(void)
{
    int ret = GSM_Command("AT^SISI=0\r", "^SISI: 0,6,", "^SISI: 0,5,", "OK", "ERROR", 5);
    if (ret == 1 || ret == 2)
        return TCP_CONNECTION_DOWN;
    else 
        return TCP_CONNECTION_UP;
}

char GSM_TCP_CloseClient_CNS01(void)
{
    int ret = GSM_Command("AT^SISC=0\r", "OK", "ERROR", NULL, NULL, 10);
    return (ret == 1);
}

extern int communication_recv_size;

int GSM_Communication_ReceivingData_CNS01(char * Buffer)
{
    int data_count = 0;
    int data_remain = 0;
    int total_data = 0;
    int count;
    char * _tmp2;
    char * _tmp;
    
    if (GSM_Command("AT^SISR=0,1024\r", "^SISR: 0,", "\r\nOK\r\n", "\r\nERROR\r\n", NULL, 5) == 1)
    {
        _tmp = gsmMessage.buff;
        
        _tmp2 = vbb_FindStr(_tmp, "^SISR: 0,");
        
        while (_tmp2)
        {
            _tmp2 += vbb_GetLen("^SISR: 0,");
            while (_tmp2[0] == NULL)
            {
                vbb_DelayMillis(20);
                vbb_GSM_Flush();
            }
            
            sscanf(_tmp2, "%d,%d", &data_count, &data_remain);      
            
            if (data_count != 0)
                vbb_CONSOLE_Printf("INFO: Received %d bytes of data.\r\n", data_count);
            
            if (data_count == -2)
            {
                if (total_data == 0)
                    return -1;
            } 
            else if (data_count > 2)
            {            
                _tmp = vbb_FindStr(_tmp2, "\r\n");
                while (_tmp == NULL)
                {
                    vbb_DelayMillis(20);
                    vbb_GSM_Flush();                
                    _tmp = vbb_FindStr(_tmp2, "\r\n");
                }
                
                _tmp += vbb_GetLen("\r\n");                                                
                
                while (vbb_GetLen(_tmp) < data_count)
                {
                    vbb_DelayMillis(20);
                    vbb_GSM_Flush();
                    //vbb_OUTPUT_Print("[!]");
                }
                
                count = data_count;
                while (count > 0)
                {                
                    Buffer[0] = _tmp[0];                
                    //vbb_OUTPUT_WriteByte(_tmp2[0]);
                    Buffer++;
                    _tmp++;
                    count--;
                }

                total_data += data_count;
                break;
            }
            else
            {
                data_count = 0;
                _tmp = _tmp2;
            }
            
            vbb_DelayMillis(20);
            vbb_GSM_Flush();
            
            if (_tmp)
                _tmp2 = vbb_FindStr(_tmp, "^SISR: 0,");
            else
                _tmp2 = NULL;
        }
    }
    return total_data;
}

#endif
